home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Ubuntu 9.10 PL / karmelkowy-koliberek-desktop-9.10-i386-PL.iso / casper / filesystem.squashfs / usr / share / hplip / ui4 / printsettingstoolbox.py < prev    next >
Encoding:
Python Source  |  2009-10-09  |  73.9 KB  |  1,945 lines

  1. # -*- coding: utf-8 -*-
  2. #
  3. # (c) Copyright 2001-2008 Hewlett-Packard Development Company, L.P.
  4. #
  5. # This program is free software; you can redistribute it and/or modify
  6. # it under the terms of the GNU General Public License as published by
  7. # the Free Software Foundation; either version 2 of the License, or
  8. # (at your option) any later version.
  9. #
  10. # This program is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. # GNU General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License
  16. # along with this program; if not, write to the Free Software
  17. # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  18. #
  19. # Authors: Don Welch
  20. #
  21.  
  22. # Std Lib
  23. import sys
  24.  
  25. # Local
  26. from base.g import *
  27. from base import utils
  28. from prnt import cups
  29. from base.codes import *
  30. from ui_utils import *
  31.  
  32. # Qt
  33. from PyQt4.QtCore import *
  34. from PyQt4.QtGui import *
  35.  
  36.  
  37.  
  38. class RangeValidator(QValidator):
  39.     def __init__(self, parent=None, name=None):
  40.         QValidator.__init__(self, parent) #, name)
  41.  
  42.  
  43.     def validate(self, input, pos):
  44.         for x in unicode(input)[pos-1:]:
  45.             if x not in u'0123456789,- ':
  46.                 return QValidator.Invalid, pos
  47.  
  48.         return QValidator.Acceptable, pos
  49.  
  50.  
  51.  
  52. class PinValidator(QValidator):
  53.     def __init__(self, parent=None, name=None):
  54.         QValidator.__init__(self, parent) #, name)
  55.  
  56.  
  57.     def validate(self, input, pos):
  58.         for x in unicode(input)[pos-1:]:
  59.             if x not in u'0123456789':
  60.                 return QValidator.Invalid, pos
  61.  
  62.         return QValidator.Acceptable, pos
  63.  
  64.  
  65.  
  66. class UsernameAndJobnameValidator(QValidator):
  67.     def __init__(self, parent=None, name=None):
  68.         QValidator.__init__(self, parent) #, name)
  69.  
  70.  
  71.     def validate(self, input, pos):
  72.         for x in unicode(input)[pos-1:]:
  73.             if x in u' /=,.:;\'"[]{}-+!@#$%^&*()':
  74.                 return QValidator.Invalid, pos
  75.  
  76.         return QValidator.Acceptable, pos
  77.  
  78.  
  79.  
  80. class OptionComboBox(QComboBox):
  81.     def __init__(self, rw, parent, name, group, option, choices, default,
  82.                  typ=cups.PPD_UI_PICKONE, other=None, job_option=False):
  83.         QComboBox.__init__(self, parent)
  84.         # rw?
  85.         self.group = group
  86.         self.option = option
  87.         self.choices = choices
  88.         self.default = default
  89.         self.typ = typ
  90.         self.other = other
  91.         self.job_option = job_option
  92.         self.setObjectName(name)
  93.  
  94.  
  95.     def setDefaultPushbutton(self, pushbutton):
  96.         self.pushbutton = pushbutton
  97.  
  98.  
  99.     def setOther(self, other):
  100.         self.other = other
  101.  
  102.  
  103.  
  104. class OptionSpinBox(QSpinBox):
  105.     def __init__(self,  parent, name, group, option, default, job_option=False):
  106.         QSpinBox.__init__(self, parent)
  107.         self.group = group
  108.         self.option = option
  109.         self.default = default
  110.         self.job_option = job_option
  111.         self.setObjectName(name)
  112.  
  113.  
  114.     def setDefaultPushbutton(self, pushbutton):
  115.         self.pushbutton = pushbutton
  116.  
  117.  
  118.  
  119. class OptionRadioButton(QRadioButton):
  120.     def __init__(self, parent, name, group, option, default, job_option=False):
  121.         QRadioButton.__init__(self, parent)
  122.         self.group = group
  123.         self.option = option
  124.         self.default = default
  125.         self.job_option = job_option
  126.         self.setObjectName(name)
  127.  
  128.  
  129.     def setDefaultPushbutton(self, pushbutton):
  130.         self.pushbutton = pushbutton
  131.  
  132.  
  133.  
  134. class DefaultPushButton(QPushButton):
  135.     def __init__(self,  parent, name, group, option, choices,
  136.                  default, control, typ, job_option=False):
  137.         QPushButton.__init__(self, parent)
  138.         self.group = group
  139.         self.option = option
  140.         self.default = default
  141.         self.control = control
  142.         self.typ = typ
  143.         self.choices = choices
  144.         self.job_option = job_option
  145.         self.setObjectName(name)
  146.  
  147.  
  148. #class PageRangeRadioButton(QRadioButton):
  149. #    def __init__(self, parent, page_range_edit):
  150. #        QRadioButton.__init__(self, parent):
  151. #            self.page_range_edit = page_range_edit
  152.  
  153.  
  154. class PageRangeRadioButton(QRadioButton):
  155.     def __init__(self, parent, name, group, option, default): #, edit_control=None ):
  156.         QRadioButton.__init__(self, parent)
  157.         self.group = group
  158.         self.option = option
  159.         self.default = default
  160.         self.job_option = True
  161.         self.setObjectName(name)
  162.  
  163.  
  164.     def setRangeEdit(self, edit_control):
  165.         self.edit_control = edit_control
  166.  
  167.  
  168.     def setDefaultPushbutton(self, pushbutton):
  169.         self.pushbutton = pushbutton
  170.  
  171.  
  172.  
  173. class PrintSettingsToolbox(QToolBox):
  174.     def __init__(self, parent, include_job_options=False):
  175.         QToolBox.__init__(self, parent)
  176.         self.include_job_options = include_job_options
  177.         self.plus_icon = QIcon(load_pixmap('plus', '16x16'))
  178.         self.minus_icon = QIcon(load_pixmap('minus', '16x16'))
  179.         self.last_item = 0
  180.         self.job_options = {}
  181.         self.job_storage_enable = False
  182.  
  183.         self.connect(self, SIGNAL("currentChanged(int)"), self.PrintSettingsToolbox_currentChanged)
  184.  
  185.  
  186.     def getPrintCommands(self, file_list=None):
  187.         # File list: [(path, mime_type, mime_desc, title, num_pages), ...]
  188.         if file_list is None or not file_list:
  189.             return []
  190.  
  191.         print_commands = []
  192.  
  193.         try:
  194.             copies = int(self.job_options['copies'])
  195.         except ValueError:
  196.             copies = 1
  197.  
  198.         if copies < 1:
  199.             copies = 1
  200.             log.warning("Copies < 1, setting to 1.")
  201.         elif copies > 99:
  202.             copies = 99
  203.             log.warning("Copies > 99, setting to 99.")
  204.  
  205.         #page_range = unicode(self.pageRangeEdit.text())
  206.         page_range = self.job_options['pagerange']
  207.  
  208.         try:
  209.             x = utils.expand_range(page_range)
  210.         except ValueError:
  211.             log.error("Invalid page range: %s" % page_range)
  212.             return []
  213.  
  214.         all_pages = not page_range
  215.         #page_set = int(self.pageSetComboBox.currentItem())
  216.         page_set = self.job_options['pageset']
  217.  
  218.         cups.resetOptions()
  219.         cups.openPPD(self.cur_printer)
  220.         current_options = dict(cups.getOptions())
  221.         cups.closePPD()
  222.  
  223.         nup = int(current_options.get("number-up", 1))
  224.         psnup = utils.which('psnup')
  225.  
  226.         for p, t, d, title, num_pages in file_list:
  227.             alt_nup = (nup > 1 and t == 'application/postscript' and psnup)
  228.  
  229.             if utils.which('lpr'):
  230.                 if alt_nup:
  231.                     cmd = ' '.join(['psnup', '-%d' % nup, ''.join(['"', p, '"']), '| lpr -P', self.cur_printer])
  232.                 else:
  233.                     cmd = ' '.join(['lpr -P', self.cur_printer])
  234.  
  235.                 if copies > 1:
  236.                     cmd = ' '.join([cmd, '-#%d' % copies])
  237.  
  238.             else: # lp
  239.                 if alt_nup:
  240.                     cmd = ' '.join(['psnup', '-%d' % nup, ''.join(['"', p, '"']), '| lp -c -d', self.cur_printer])
  241.                 else:
  242.                     cmd = ' '.join(['lp -c -d', self.cur_printer])
  243.  
  244.                 if copies > 1:
  245.                     cmd = ' '.join([cmd, '-n%d' % copies])
  246.  
  247.  
  248.             if not all_pages and page_range:
  249.                 cmd = ' '.join([cmd, '-o page-ranges=%s' % page_range])
  250.  
  251.             if page_set:
  252.                 cmd = ' '.join([cmd, '-o page-set=%s' % page_set])
  253.  
  254.             # Job Storage
  255.             # self.job_storage_mode = (0=Off, 1=P&H, 2=PJ, 3=QC, 4=SJ)
  256.             # self.job_storage_pin = u"" (dddd)
  257.             # self.job_storage_use_pin = True|False
  258.             # self.job_storage_username = u""
  259.             # self.job_storage_auto_username = True|False
  260.             # self.job_storage_jobname = u""
  261.             # self.job_storage_auto_jobname = True|False
  262.             # self.job_storage_job_exist = (0=replace, 1=job name+(1-99))
  263.  
  264.             if self.job_storage_enable:
  265.                 if self.job_storage_mode != JOB_STORAGE_TYPE_OFF:
  266.                     if self.job_storage_mode == JOB_STORAGE_TYPE_PROOF_AND_HOLD:
  267.                         cmd = ' '.join([cmd, '-o HOLD=PROOF'])
  268.  
  269.                     elif self.job_storage_mode == JOB_STORAGE_TYPE_PERSONAL:
  270.                         if self.job_storage_use_pin:
  271.                             cmd = ' '.join([cmd, '-o HOLD=ON'])
  272.                             cmd = ' '.join([cmd, '-o HOLDTYPE=PRIVATE'])
  273.                             cmd = ' '.join([cmd, '-o HOLDKEY=%s' % self.job_storage_pin.encode('ascii')])
  274.                         else:
  275.                             cmd = ' '.join([cmd, '-o HOLD=PROOF'])
  276.                             cmd = ' '.join([cmd, '-o HOLDTYPE=PRIVATE'])
  277.  
  278.                     elif self.job_storage_mode == JOB_STORAGE_TYPE_QUICK_COPY:
  279.                         cmd = ' '.join([cmd, '-o HOLD=ON'])
  280.                         cmd = ' '.join([cmd, '-o HOLDTYPE=PUBLIC'])
  281.  
  282.                     elif self.job_storage_mode == JOB_STORAGE_TYPE_STORE:
  283.                         if self.job_storage_use_pin:
  284.                             cmd = ' '.join([cmd, '-o HOLD=STORE'])
  285.                             cmd = ' '.join([cmd, '-o HOLDTYPE=PRIVATE'])
  286.                             cmd = ' '.join([cmd, '-o HOLDKEY=%s' % self.job_storage_pin.encode('ascii')])
  287.                         else:
  288.                             cmd = ' '.join([cmd, '-o HOLD=STORE'])
  289.  
  290.                     cmd = ' '.join([cmd, '-o USERNAME=%s' % self.job_storage_username.encode('ascii')\
  291.                         .replace(" ", "_")])
  292.  
  293.                     cmd = ' '.join([cmd, '-o JOBNAME=%s' % self.job_storage_jobname.encode('ascii')\
  294.                         .replace(" ", "_")])
  295.  
  296.                     if self.job_storage_job_exist == 1:
  297.                         cmd = ' '.join([cmd, '-o DUPLICATEJOB=APPEND'])
  298.                     else:
  299.                         cmd = ' '.join([cmd, '-o DUPLICATEJOB=REPLACE'])
  300.  
  301.                 else: # Off
  302.                     cmd = ' '.join([cmd, '-o HOLD=OFF'])
  303.  
  304.             if not alt_nup:
  305.                 cmd = ''.join([cmd, ' "', p, '"'])
  306.  
  307.             print_commands.append(cmd)
  308.  
  309.         return print_commands
  310.  
  311.  
  312.     def PrintSettingsToolbox_currentChanged(self, i):
  313.         if i != -1:
  314.             self.setItemIcon(self.last_item, self.plus_icon)
  315.             self.setItemIcon(i, self.minus_icon)
  316.             self.last_item = i
  317.  
  318.  
  319.     def updateUi(self, cur_device, cur_printer):
  320.         #print "updateUi(%s, %s)" % (cur_device, cur_printer)
  321.         self.cur_device = cur_device
  322.         self.cur_printer = cur_printer
  323.  
  324.         while self.count():
  325.             self.removeItem(0)
  326.  
  327.         self.loading = True
  328.         cups.resetOptions()
  329.         cups.openPPD(self.cur_printer)
  330.  
  331.         try:
  332.             if 1:
  333.             #try:
  334.                 current_options = dict(cups.getOptions())
  335.  
  336.                 if self.include_job_options:
  337.                     self.beginControlGroup("job_options", self.__tr("Job Options"))
  338.  
  339.                     # Num. copies (SPINNER)
  340.                     try:
  341.                         current = int(current_options.get('copies', '1'))
  342.                     except ValueError:
  343.                         current = 1
  344.  
  345.                     self.addControlRow("copies", self.__tr("Number of copies"),
  346.                         cups.UI_SPINNER, current, (1, 99), 1, job_option=True)
  347.                     self.job_options['copies'] = current
  348.  
  349.                     # page range RADIO + RANGE (custom)
  350.                     current = current_options.get('pagerange', '')
  351.  
  352.                     self.addControlRow("pagerange", self.__tr("Page Range"),
  353.                         cups.UI_PAGE_RANGE, current, None, None, job_option=True)
  354.  
  355.                     self.job_options['pagerange'] = current
  356.  
  357.                     # page set (COMBO/PICKONE)
  358.                     current = current_options.get('pageset', '')
  359.                     self.addControlRow("pageset", self.__tr("Page Set"),
  360.                         cups.PPD_UI_PICKONE, current,
  361.                         [('all', self.__tr("All pages")),
  362.                          ('even', self.__tr("Even pages")),
  363.                          ('odd', self.__tr("Odd pages"))], 'all', job_option=True)
  364.  
  365.                     self.job_options['pageset'] = current
  366. #                    if current == u'even':
  367. #                        self.job_options["pageset"] = PAGE_SET_EVEN
  368. #                    elif current == u'odd':
  369. #                        self.job_options["pageset"] = PAGE_SET_ODD
  370. #                    else:
  371. #                        self.job_options["pageset"] = PAGE_SET_ALL
  372.  
  373.                     self.endControlGroup() # job_options
  374.  
  375.                 if not self.cur_device.device_type == DEVICE_TYPE_FAX:
  376.                     self.beginControlGroup("basic", self.__tr("Basic"))
  377.  
  378.                     # Basic
  379.                         # PageSize (in PPD section)
  380.                         # orientation-requested
  381.                         # sides
  382.                         # outputorder
  383.                         # Collate
  384.  
  385.                     current = current_options.get('orientation-requested', '3')
  386.  
  387.                     self.addControlRow("orientation-requested", self.__tr("Page Orientation"),
  388.                         cups.PPD_UI_PICKONE, current,
  389.                         [('3', self.__tr('Portrait')),
  390.                          ('4', self.__tr('Landscape')),
  391.                          ('5', self.__tr('Reverse landscape')),
  392.                          ('6', self.__tr('Reverse portrait'))], '3')
  393.  
  394.                     log.debug("Option: orientation-requested")
  395.                     log.debug("Current value: %s" % current)
  396.  
  397.                     duplexer = self.cur_device.dq.get('duplexer', 0)
  398.                     log.debug("Duplexer = %d" % duplexer)
  399.  
  400.                     if duplexer:
  401.                         current = current_options.get('sides', 'one-sided')
  402.                         self.addControlRow("sides",
  403.                             self.__tr("Duplex (Print on both sides of the page)"),
  404.                             cups.PPD_UI_PICKONE, current,
  405.                             [('one-sided',self.__tr('Single sided')),
  406.                              ('two-sided-long-edge', self.__tr('Two sided (long edge)')),
  407.                              ('two-sided-short-edge', self.__tr('Two sided (short edge)'))], 'one-sided')
  408.  
  409.                         log.debug("Option: sides")
  410.                         log.debug("Current value: %s" % current)
  411.  
  412.                     current = current_options.get('outputorder', 'normal')
  413.  
  414.                     self.addControlRow("outputorder",
  415.                         self.__tr("Output Order (Print last page first)"),
  416.                         cups.PPD_UI_PICKONE, current,
  417.                         [('normal', self.__tr('Normal (Print first page first)')),
  418.                          ('reverse', self.__tr('Reversed (Print last page first)'))], 'normal')
  419.  
  420.                     log.debug("Option: outputorder")
  421.                     log.debug("Current value: %s" % current)
  422.  
  423.                     current = utils.to_bool(current_options.get('Collate', '0'))
  424.  
  425.                     self.addControlRow("Collate",
  426.                         self.__tr("Collate (Group together multiple copies)"),
  427.                         cups.PPD_UI_BOOLEAN, current,
  428.                         [], 0)
  429.  
  430.                     log.debug("Option: Collate")
  431.                     log.debug("Current value: %s" % current)
  432.  
  433.                     self.endControlGroup()
  434.  
  435.                 groups = cups.getGroupList()
  436.  
  437.                 #print groups
  438.  
  439.                 for g in groups:
  440.                     if 'jobretention' in g.lower():
  441.                         log.debug("HPJobRetention skipped.")
  442.                         continue
  443.  
  444.                     try:
  445.                         text, num_subgroups = cups.getGroup(g)
  446.                     except TypeError:
  447.                         log.warn("Group %s returned None" % g)
  448.                         continue
  449.  
  450.                     read_only = 'install' in g.lower()
  451.  
  452.                     try:
  453.                         text = text.decode('utf-8')
  454.                     except UnicodeDecodeError:
  455.                         pass
  456.  
  457.                     if g.lower() == 'printoutmode':
  458.                         text = self.__tr("Quality (also see 'Printout Mode' under 'General')")
  459.  
  460.                     self.beginControlGroup(g, QString(text))
  461.  
  462.                     log.debug("  Text: %s" % unicode(text))
  463.                     log.debug("Num subgroups: %d" % num_subgroups)
  464.  
  465.                     options = cups.getOptionList(g)
  466.  
  467.                     #print options
  468.  
  469.                     for o in options:
  470.                         log.debug("  Option: %s" % repr(o))
  471.  
  472.                         if 'pageregion' in o.lower():
  473.                             log.debug("Page Region skipped.")
  474.                             continue
  475.  
  476.                         try:
  477.                             option_text, defchoice, conflicted, ui  = cups.getOption(g, o)
  478.                         except TypeError:
  479.                             log.warn("Option %s in group %s returned None" % (o, g))
  480.                             continue
  481.  
  482.                         try:
  483.                             option_text = option_text.decode('utf-8')
  484.                         except UnicodeDecodeError:
  485.                             pass
  486.  
  487.                         if o.lower() == 'quality':
  488.                             option_text = self.__tr("Quality")
  489.  
  490.                         log.debug("    Text: %s" % repr(option_text))
  491.                         log.debug("    Defchoice: %s" % repr(defchoice))
  492.  
  493.                         choices = cups.getChoiceList(g, o)
  494.  
  495.                         value = None
  496.                         choice_data = []
  497.                         for c in choices:
  498.                             log.debug("    Choice: %s" % repr(c))
  499.  
  500.                             # TODO: Add custom paper size controls
  501.                             if 'pagesize' in o.lower() and 'custom' in c.lower():
  502.                                 log.debug("Skipped.")
  503.                                 continue
  504.  
  505.                             choice_text, marked = cups.getChoice(g, o, c)
  506.  
  507.                             try:
  508.                                 choice_text = choice_text.decode('utf-8')
  509.                             except UnicodeDecodeError:
  510.                                 pass
  511.  
  512.                             log.debug("      Text: %s" % repr(choice_text))
  513.  
  514.                             if marked:
  515.                                 value = c
  516.  
  517.                             choice_data.append((c, choice_text))
  518.  
  519.                         self.addControlRow(o, option_text, ui, value, choice_data, defchoice, read_only)
  520.  
  521.                     self.endControlGroup()
  522.  
  523. ##                        if 'pagesize' in o.lower(): # and 'custom' in c.lower():
  524. ##                            current = 0.0
  525. ##                            width_widget = self.addControlRow(widget, "custom", "custom-width", self.__tr("Custom Paper Width"), cups.UI_UNITS_SPINNER,
  526. ##                                current, (0.0, 0.0), 0.0)
  527. ##
  528. ##                            current = 0.0
  529. ##                            height_widget = self.addControlRow("custom", "custom-height", self.__tr("Custom Paper Height"), cups.UI_UNITS_SPINNER,
  530. ##                                current, (0.0, 0.0), 0.0)
  531. ##
  532. ##                            if value.lower() == 'custom':
  533. ##                                pass
  534.  
  535.                 # N-Up
  536.                     # number-up
  537.                     # number-up-layout
  538.                     # page-border
  539.  
  540.                 self.beginControlGroup("nup", self.__tr("N-Up (Multiple document pages per printed page)"))
  541.                 current = current_options.get('number-up', '1')
  542.  
  543.                 self.addControlRow("number-up", self.__tr("Pages per Sheet"),
  544.                     cups.PPD_UI_PICKONE, current,
  545.                     [('1', self.__tr('1 page per sheet')),
  546.                      ('2', self.__tr('2 pages per sheet')),
  547.                      ('4', self.__tr('4 pages per sheet'))], '1')
  548.  
  549.                 log.debug("  Option: number-up")
  550.                 log.debug("  Current value: %s" % current)
  551.  
  552.                 current = current_options.get('number-up-layout', 'lrtb')
  553.  
  554.                 self.addControlRow("number-up-layout", self.__tr("Layout"),
  555.                     cups.PPD_UI_PICKONE, current,
  556.                     [('btlr', self.__tr('Bottom to top, left to right')),
  557.                      ('btrl', self.__tr('Bottom to top, right to left')),
  558.                      ('lrbt', self.__tr('Left to right, bottom to top')),
  559.                      ('lrtb', self.__tr('Left to right, top to bottom')),
  560.                      ('rlbt', self.__tr('Right to left, bottom to top')),
  561.                      ('rltb', self.__tr('Right to left, top to bottom')),
  562.                      ('tblr', self.__tr('Top to bottom, left to right')),
  563.                      ('tbrl', self.__tr('Top to bottom, right to left')) ], 'lrtb')
  564.  
  565.                 log.debug("  Option: number-up-layout")
  566.                 log.debug("  Current value: %s" % current)
  567.  
  568.                 current = current_options.get('page-border', 'none')
  569.  
  570.                 self.addControlRow("page-border",
  571.                     self.__tr("Printed Border Around Each Page"),
  572.                     cups.PPD_UI_PICKONE, current,
  573.                     [('double', self.__tr("Two thin borders")),
  574.                      ("double-thick", self.__tr("Two thick borders")),
  575.                      ("none", self.__tr("No border")),
  576.                      ("single", self.__tr("One thin border")),
  577.                      ("single-thick", self.__tr("One thick border"))], 'none')
  578.  
  579.                 log.debug("  Option: page-border")
  580.                 log.debug("  Current value: %s" % current)
  581.  
  582.                 self.endControlGroup()
  583.  
  584.                 # Adjustment
  585.                     # brightness
  586.                     # gamma
  587.  
  588.                 if not self.cur_device.device_type == DEVICE_TYPE_FAX:
  589.                     self.beginControlGroup("adjustment", self.__tr("Printout Appearance"))
  590.  
  591.                     current = int(current_options.get('brightness', 100))
  592.  
  593.                     log.debug("  Option: brightness")
  594.                     log.debug("  Current value: %s" % current)
  595.  
  596.                     self.addControlRow("brightness", self.__tr("Brightness"),
  597.                         cups.UI_SPINNER, current, (0, 200), 100, suffix=" %")
  598.  
  599.                     current = int(current_options.get('gamma', 1000))
  600.  
  601.                     log.debug("  Option: gamma")
  602.                     log.debug("  Current value: %s" % current)
  603.  
  604.                     self.addControlRow("gamma", self.__tr("Gamma"), cups.UI_SPINNER, current,
  605.                         (1, 10000), 1000)
  606.  
  607.                     self.endControlGroup()
  608.  
  609.                 # Margins (pts)
  610.                     # page-left
  611.                     # page-right
  612.                     # page-top
  613.                     # page-bottom
  614.  
  615. ##                if 0:
  616. ##                    # TODO: cupsPPDPageSize() fails on LaserJets. How do we get margins in this case? Defaults?
  617. ##                    # PPD file for LJs has a HWMargin entry...
  618. ##                    page, page_width, page_len, left, bottom, right, top = cups.getPPDPageSize()
  619. ##
  620. ##                    right = page_width - right
  621. ##                    top = page_len - top
  622. ##
  623. ##                    self.addGroupHeading("margins", self.__tr("Margins"))
  624. ##                    current_top = current_options.get('page-top', 0) # pts
  625. ##                    current_bottom = current_options.get('page-bottom', 0) # pts
  626. ##                    current_left = current_options.get('page-left', 0) # pts
  627. ##                    current_right = current_options.get('page-right', 0) # pts
  628. ##
  629. ##                    log.debug("  Option: page-top")
  630. ##                    log.debug("  Current value: %s" % current_top)
  631. ##
  632. ##                    self.addControlRow("margins", "page-top", self.__tr("Top margin"),
  633. ##                        cups.UI_UNITS_SPINNER, current_top,
  634. ##                        (0, page_len), top)
  635. ##
  636. ##                    self.addControlRow("margins", "page-bottom", self.__tr("Bottom margin"),
  637. ##                        cups.UI_UNITS_SPINNER, current_bottom,
  638. ##                        (0, page_len), bottom)
  639. ##
  640. ##                    self.addControlRow("margins", "page-left", self.__tr("Right margin"),
  641. ##                        cups.UI_UNITS_SPINNER, current_left,
  642. ##                        (0, page_width), left)
  643. ##
  644. ##                    self.addControlRow("margins", "page-right", self.__tr("Left margin"),
  645. ##                        cups.UI_UNITS_SPINNER, current_right,
  646. ##                        (0, page_width), right)
  647.  
  648.                 # Image Printing
  649.                     # position
  650.                     # natural-scaling
  651.                     # saturation
  652.                     # hue
  653.  
  654.                 self.beginControlGroup("image", self.__tr("Image Printing"))
  655.  
  656.                 current = utils.to_bool(current_options.get('fitplot', 'false'))
  657.  
  658.                 self.addControlRow("fitplot",
  659.                     self.__tr("Fit to Page"),
  660.                     cups.PPD_UI_BOOLEAN, current,
  661.                     [], 0)
  662.  
  663.                 current = current_options.get('position', 'center')
  664.  
  665.                 self.addControlRow("position", self.__tr("Position on Page"),
  666.                     cups.PPD_UI_PICKONE, current,
  667.                     [('center', self.__tr('Centered')),
  668.                      ('top', self.__tr('Top')),
  669.                      ('left', self.__tr('Left')),
  670.                      ('right', self.__tr('Right')),
  671.                      ('top-left', self.__tr('Top left')),
  672.                      ('top-right', self.__tr('Top right')),
  673.                      ('bottom', self.__tr('Bottom')),
  674.                      ('bottom-left', self.__tr('Bottom left')),
  675.                      ('bottom-right', self.__tr('Bottom right'))], 'center')
  676.  
  677.                 log.debug("  Option: position")
  678.                 log.debug("  Current value: %s" % current)
  679.  
  680.                 if not self.cur_device.device_type == DEVICE_TYPE_FAX:
  681.                     current = int(current_options.get('saturation', 100))
  682.  
  683.                     log.debug("  Option: saturation")
  684.                     log.debug("  Current value: %s" % current)
  685.  
  686.                     self.addControlRow("saturation", self.__tr("Saturation"),
  687.                         cups.UI_SPINNER, current, (0, 200), 100, suffix=" %")
  688.  
  689.                     current = int(current_options.get('hue', 0))
  690.  
  691.                     log.debug("  Option: hue")
  692.                     log.debug("  Current value: %s" % current)
  693.  
  694.                     self.addControlRow("hue", self.__tr("Hue (color shift/rotation)"),
  695.                         cups.UI_SPINNER, current,
  696.                         (-100, 100), 0)
  697.  
  698.                 current = int(current_options.get('natural-scaling', 100))
  699.  
  700.                 log.debug("  Option: natural-scaling")
  701.                 log.debug("  Current value: %s" % current)
  702.  
  703.                 self.addControlRow("natural-scaling",
  704.                     self.__tr('"Natural" Scaling (relative to image)'),
  705.                     cups.UI_SPINNER, current, (1, 800), 100, suffix=" %")
  706.  
  707.                 current = int(current_options.get('scaling', 100))
  708.  
  709.                 log.debug("  Option: scaling")
  710.                 log.debug("  Current value: %s" % current)
  711.  
  712.                 self.addControlRow("scaling", self.__tr("Scaling (relative to page)"),
  713.                     cups.UI_SPINNER, current,
  714.                     (1, 800), 100, suffix=" %")
  715.  
  716.                 self.endControlGroup()
  717.  
  718.                 # Misc
  719.                     # PrettyPrint
  720.                     # job-sheets
  721.                     # mirror
  722.  
  723.                 self.beginControlGroup("misc", self.__tr("Miscellaneous"))
  724.  
  725.                 log.debug("Group: Misc")
  726.  
  727.                 current = utils.to_bool(current_options.get('prettyprint', '0'))
  728.  
  729.                 self.addControlRow("prettyprint",
  730.                     self.__tr('"Pretty Print" Text Documents (Add headers and formatting)'),
  731.                     cups.PPD_UI_BOOLEAN, current, [], 0)
  732.  
  733.                 log.debug("  Option: prettyprint")
  734.                 log.debug("  Current value: %s" % current)
  735.  
  736.                 if not self.cur_device.device_type == DEVICE_TYPE_FAX:
  737.                     current = current_options.get('job-sheets', 'none').split(',')
  738.  
  739.                     try:
  740.                         start = current[0]
  741.                     except IndexError:
  742.                         start = 'none'
  743.  
  744.                     try:
  745.                         end = current[1]
  746.                     except IndexError:
  747.                         end = 'none'
  748.  
  749.                     # TODO: Look for locally installed banner pages beyond the default CUPS ones?
  750.                     self.addControlRow("job-sheets", self.__tr("Banner Pages"), cups.UI_BANNER_JOB_SHEETS,
  751.                         (start, end),
  752.                         [("none", self.__tr("No banner page")),
  753.                          ('classified', self.__tr("Classified")),
  754.                          ('confidential', self.__tr("Confidential")),
  755.                          ('secret', self.__tr("Secret")),
  756.                          ('standard', self.__tr("Standard")),
  757.                          ('topsecret', self.__tr("Top secret")),
  758.                          ('unclassified', self.__tr("Unclassified"))], ('none', 'none'))
  759.  
  760.                     log.debug("  Option: job-sheets")
  761.                     log.debug("  Current value: %s,%s" % (start, end))
  762.  
  763.                 current = utils.to_bool(current_options.get('mirror', '0'))
  764.  
  765.                 self.addControlRow("mirror", self.__tr('Mirror Printing'),
  766.                     cups.PPD_UI_BOOLEAN, current, [], 0)
  767.  
  768.                 log.debug("  Option: mirror")
  769.                 log.debug("  Current value: %s" % current)
  770.  
  771.                 self.endControlGroup()
  772.  
  773.                 self.job_storage_enable = self.cur_device.mq.get('job-storage', JOB_STORAGE_DISABLE) == JOB_STORAGE_ENABLE
  774.  
  775.  
  776.                 if self.job_storage_enable:
  777.                     self.job_storage_pin = unicode(current_options.get('HOLDKEY', '0000')[:4])
  778.                     self.job_storage_username = unicode(current_options.get('USERNAME', prop.username)[:16])
  779.                     self.job_storage_jobname = unicode(current_options.get('JOBNAME', u'Untitled')[:16])
  780.                     hold = unicode(current_options.get('HOLD', u'OFF'))
  781.                     holdtype = unicode(current_options.get('HOLDTYPE', u'PUBLIC'))
  782.                     self.job_storage_use_pin = False
  783.                     duplicate = unicode(current_options.get('DUPLICATEJOB', u'REPLACE'))
  784.                     self.job_storage_auto_username = True
  785.                     self.job_storage_auto_jobname = True
  786.                     self.job_storage_mode = JOB_STORAGE_TYPE_OFF
  787.  
  788.                     if hold == 'OFF':
  789.                         self.job_storage_mode = JOB_STORAGE_TYPE_OFF
  790.  
  791.                     elif hold == 'ON':
  792.                         if holdtype == u'PUBLIC':
  793.                             self.job_storage_mode = JOB_STORAGE_TYPE_QUICK_COPY
  794.  
  795.                         else: # 'PRIVATE'
  796.                             self.job_storage_mode = JOB_STORAGE_TYPE_PERSONAL
  797.                             self.job_storage_use_pin = True
  798.  
  799.                     elif hold == u'PROOF':
  800.                         if holdtype == u'PUBLIC':
  801.                             self.job_storage_mode = JOB_STORAGE_TYPE_PROOF_AND_HOLD
  802.                         else:
  803.                             self.job_storage_mode = JOB_STORAGE_TYPE_PERSONAL
  804.                             self.job_storage_use_pin = True
  805.  
  806.                     elif hold == u'STORE':
  807.                         self.job_storage_mode = JOB_STORAGE_TYPE_STORE
  808.                         self.job_storage_use_pin = (holdtype == u'PRIVATE')
  809.  
  810.                     if duplicate == u'REPLACE':
  811.                         self.job_storage_job_exist = JOB_STORAGE_EXISTING_JOB_REPLACE
  812.                     else: # u'APPEND'
  813.                         self.job_storage_job_exist = JOB_STORAGE_EXISTING_JOB_APPEND_1_99
  814.  
  815.                     # option, text, typ, value, choices, default, read_only=False, suffix="", job_option=False)
  816.  
  817.                     self.beginControlGroup("jobstorage", self.__tr("Job Storage and Secure Printing"))
  818.  
  819.                     self.addControlRow("job-storage-mode", self.__tr("Mode"),
  820.                                        cups.UI_JOB_STORAGE_MODE, None, None, None)
  821.  
  822.                     self.addControlRow("job-storage-pin", self.__tr("Make job private (use PIN to print)"),
  823.                                       cups.UI_JOB_STORAGE_PIN, None, None, None )
  824.  
  825.                     self.addControlRow("job-storage-username", self.__tr("User name (for job identification)"),
  826.                                        cups.UI_JOB_STORAGE_USERNAME, None, None, None)
  827.  
  828.                     self.addControlRow("job-storage-id", self.__tr("Job name/ID (for job identification)"),
  829.                                       cups.UI_JOB_STORAGE_ID, None, None, None)
  830.  
  831.                     self.addControlRow("job-storage-id-exists", self.__tr("If job name/ID already exists..."),
  832.                                        cups.UI_JOB_STORAGE_ID_EXISTS, None, None, None)
  833.  
  834.                     self.endControlGroup()
  835.                     self.updateJobStorageControls()
  836.  
  837.                 # use: self.job_options['xxx'] so that values can be picked up by getPrintCommand(
  838.  
  839.  
  840.             #except Exception, e:
  841.                 #log.exception()
  842.             #    pass
  843.  
  844.         finally:
  845.             cups.closePPD()
  846.             self.loading = False
  847.  
  848.  
  849.     def beginControlGroup(self, group, text):
  850.         log.debug("BeginGroup: %s" % group)
  851.         self.row = 0
  852.         self.widget = QWidget()
  853.         self.gridlayout = QGridLayout(self.widget)
  854.         self.group = group
  855.         self.text = text
  856.  
  857.  
  858.     def endControlGroup(self):
  859.         log.debug("EndGroup: %s" % self.group)
  860.         spacer = QSpacerItem(20, 20, QSizePolicy.Minimum, QSizePolicy.Expanding)
  861.         self.row += 1
  862.         self.gridlayout.addItem(spacer, self.row, 0, 1, 1)
  863.         i = self.addItem(self.widget, self.text)
  864.  
  865.         if i:
  866.             self.setItemIcon(i, self.plus_icon)
  867.         else:
  868.             self.setItemIcon(i, self.minus_icon)
  869.  
  870.         self.widget, self.gridlayout = None, None
  871.  
  872.  
  873.     def addControlRow(self, option, text, typ, value, choices, default, read_only=False, suffix="", job_option=False):
  874.  
  875.         if typ == cups.PPD_UI_BOOLEAN: # () On (*) Off widget
  876.             HBoxLayout = QHBoxLayout()
  877.             HBoxLayout.setObjectName("HBoxLayout")
  878.  
  879.             OptionLabel = QLabel(self.widget)
  880.             OptionLabel.setObjectName("OptionLabel")
  881.             HBoxLayout.addWidget(OptionLabel)
  882.  
  883.             SpacerItem = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
  884.             HBoxLayout.addItem(SpacerItem)
  885.  
  886.             GroupBox = QFrame(self.widget)
  887.  
  888.             gridlayout1 = QGridLayout(GroupBox)
  889.             OnRadioButton = OptionRadioButton(GroupBox, "OnRadioButton", self.group,
  890.                                               option, default, job_option)
  891.             gridlayout1.addWidget(OnRadioButton,0,0,1,1)
  892.             OffRadioButton = OptionRadioButton(GroupBox, "OffRadioButton", self.group,
  893.                                                option, default, job_option)
  894.             gridlayout1.addWidget(OffRadioButton,0,1,1,1)
  895.             HBoxLayout.addWidget(GroupBox)
  896.  
  897.             DefaultButton = DefaultPushButton(self.widget, "defaultPushButton", self.group, option,
  898.                 choices, default, (OnRadioButton, OffRadioButton), typ, job_option)
  899.  
  900.             #GroupBox.setDefaultPushbutton(DefaultButton)
  901.             OnRadioButton.setDefaultPushbutton(DefaultButton)
  902.             OffRadioButton.setDefaultPushbutton(DefaultButton)
  903.  
  904.             HBoxLayout.addWidget(DefaultButton)
  905.             self.gridlayout.addLayout(HBoxLayout, self.row, 0, 1, 1)
  906.  
  907.             OptionLabel.setText(text)
  908.             OnRadioButton.setText(self.__tr("On"))
  909.             OffRadioButton.setText(self.__tr("Off"))
  910.  
  911.             DefaultButton.setText("Default")
  912.  
  913.             if value == default:
  914.                 DefaultButton.setEnabled(False)
  915.             self.connect(DefaultButton, SIGNAL("clicked()"), self.DefaultButton_clicked)
  916.  
  917.             if value:
  918.                 OnRadioButton.setChecked(True)
  919.             else:
  920.                 OffRadioButton.setChecked(True)
  921.             self.connect(OnRadioButton, SIGNAL("toggled(bool)"), self.BoolRadioButtons_clicked)
  922.  
  923.             if read_only:
  924.                 OnRadioButton.setEnabled(False)
  925.                 OffRadioButton.setEnabled(False)
  926.                 DefaultButton.setEnabled(False)
  927.  
  928.  
  929.  
  930.         elif typ == cups.PPD_UI_PICKONE: # Combo box widget
  931.             #print option, job_option
  932.             HBoxLayout = QHBoxLayout()
  933.             HBoxLayout.setObjectName("HBoxLayout")
  934.  
  935.             OptionLabel = QLabel(self.widget)
  936.             OptionLabel.setObjectName("OptionLabel")
  937.             HBoxLayout.addWidget(OptionLabel)
  938.  
  939.             SpacerItem = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
  940.             HBoxLayout.addItem(SpacerItem)
  941.  
  942.             ComboBox = OptionComboBox(0, self.widget, "ComboBox", self.group, option,
  943.                                       choices, default, typ, None, job_option)
  944.  
  945.             HBoxLayout.addWidget(ComboBox)
  946.  
  947.             DefaultButton = DefaultPushButton(self.widget, "DefaultButton", self.group, option,
  948.                 choices, default, ComboBox, typ, job_option)
  949.  
  950.             ComboBox.setDefaultPushbutton(DefaultButton)
  951.             HBoxLayout.addWidget(DefaultButton)
  952.  
  953.             self.gridlayout.addLayout(HBoxLayout, self.row, 0, 1, 1)
  954.  
  955.             OptionLabel.setText(text)
  956.             DefaultButton.setText("Default")
  957.  
  958.             i, x, y = 0, None, None
  959.             for c, t in choices:
  960.                 d = c.lower()
  961.                 if value is not None and d == value.lower():
  962.                     x = i
  963.  
  964.                 if d == default.lower():
  965.                     y = t
  966.  
  967.                 ComboBox.insertItem(i, t)
  968.                 i += 1
  969.  
  970.             if x is not None:
  971.                 ComboBox.setCurrentIndex(x)
  972.             else:
  973.                 ComboBox.setCurrentIndex(0)
  974.  
  975.             if value is not None and value.lower() == default.lower():
  976.                 DefaultButton.setEnabled(False)
  977.  
  978.             #self.linkPrintoutModeAndQuality(option, value)
  979. #
  980. #            if read_only:
  981. #                optionComboBox.setEnabled(False)
  982. #                defaultPushButton.setEnabled(False)
  983. #            elif y is not None:
  984. #                QToolTip.add(defaultPushButton, self.__tr('Set to default value of "%1".').arg(y))
  985. #
  986.  
  987.             self.connect(DefaultButton, SIGNAL("clicked()"), self.DefaultButton_clicked)
  988.             self.connect(ComboBox, SIGNAL("highlighted(const QString &)"), self.ComboBox_highlighted)
  989.  
  990.             control = ComboBox
  991.  
  992.         elif typ == cups.UI_SPINNER: # Spinner widget
  993.  
  994.             HBoxLayout = QHBoxLayout()
  995.             HBoxLayout.setObjectName("HBoxLayout")
  996.  
  997.             OptionLabel = QLabel(self.widget)
  998.             OptionLabel.setObjectName("OptionLabel")
  999.             HBoxLayout.addWidget(OptionLabel)
  1000.  
  1001.             SpacerItem = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
  1002.             HBoxLayout.addItem(SpacerItem)
  1003.  
  1004.             SpinBox = OptionSpinBox(self.widget,"SpinBox", self.group, option, default, job_option)
  1005.             HBoxLayout.addWidget(SpinBox)
  1006.  
  1007.             DefaultButton = DefaultPushButton(self.widget,"DefaultButton", self.group, option,
  1008.                 choices, default, SpinBox, typ, job_option)
  1009.  
  1010.             SpinBox.setDefaultPushbutton(DefaultButton)
  1011.             HBoxLayout.addWidget(DefaultButton)
  1012.  
  1013.             self.gridlayout.addLayout(HBoxLayout, self.row, 0, 1, 1)
  1014.  
  1015.             min, max = choices
  1016.             SpinBox.setMinimum(min)
  1017.             SpinBox.setMaximum(max)
  1018.             SpinBox.setValue(value)
  1019.  
  1020.             if suffix:
  1021.                 SpinBox.setSuffix(suffix)
  1022.  
  1023.             OptionLabel.setText(text)
  1024.             DefaultButton.setText("Default")
  1025.  
  1026.             self.connect(SpinBox, SIGNAL("valueChanged(int)"), self.SpinBox_valueChanged)
  1027.             self.connect(DefaultButton, SIGNAL("clicked()"), self.DefaultButton_clicked)
  1028.  
  1029.             DefaultButton.setEnabled(not value == default)
  1030.  
  1031.             if read_only:
  1032.                 SpinBox.setEnabled(False)
  1033.                 DefaultButton.setEnabled(False)
  1034.  
  1035.         elif typ == cups.UI_BANNER_JOB_SHEETS:  # Job sheets widget
  1036.             HBoxLayout = QHBoxLayout()
  1037.             HBoxLayout.setObjectName("HBoxLayout")
  1038.  
  1039.             OptionLabel = QLabel(self.widget)
  1040.             OptionLabel.setObjectName("OptionLabel")
  1041.             HBoxLayout.addWidget(OptionLabel)
  1042.  
  1043.             SpacerItem = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
  1044.             HBoxLayout.addItem(SpacerItem)
  1045.  
  1046.             StartLabel = QLabel(self.widget)
  1047.             HBoxLayout.addWidget(StartLabel)
  1048.  
  1049.             StartComboBox = OptionComboBox(0, self.widget, "StartComboBox", self.group,
  1050.                 "start", choices, default, typ)
  1051.  
  1052.             HBoxLayout.addWidget(StartComboBox)
  1053.  
  1054.             EndLabel = QLabel(self.widget)
  1055.             HBoxLayout.addWidget(EndLabel)
  1056.  
  1057.             EndComboBox = OptionComboBox(0, self.widget, "EndComboBox", self.group, "end", choices,
  1058.                 default, typ, StartComboBox)
  1059.  
  1060.             HBoxLayout.addWidget(EndComboBox)
  1061.  
  1062.             StartComboBox.setOther(EndComboBox)
  1063.  
  1064.             DefaultButton = DefaultPushButton(self.widget, "DefaultButton", self.group, option, choices,
  1065.                 default, (StartComboBox, EndComboBox), typ, job_option)
  1066.  
  1067.             HBoxLayout.addWidget(DefaultButton)
  1068.  
  1069.             self.gridlayout.addLayout(HBoxLayout, self.row, 0, 1, 1)
  1070.  
  1071.             StartComboBox.setDefaultPushbutton(DefaultButton)
  1072.             EndComboBox.setDefaultPushbutton(DefaultButton)
  1073.  
  1074.             OptionLabel.setText(text)
  1075.             DefaultButton.setText("Default")
  1076.  
  1077.             StartLabel.setText(self.__tr("Start:"))
  1078.             EndLabel.setText(self.__tr("End:"))
  1079.  
  1080.             s, e, y, z = None, None, None, None
  1081.             for c, t in choices:
  1082.                 d = c.lower()
  1083.                 if value is not None:
  1084.                     if d == value[0].lower():
  1085.                         s = t
  1086.  
  1087.                     if d == value[1].lower():
  1088.                         e = t
  1089.  
  1090.                 if d == default[0].lower():
  1091.                     y = t
  1092.  
  1093.                 if d == default[1].lower():
  1094.                     z = t
  1095.  
  1096.                 StartComboBox.insertItem(0, t)
  1097.                 EndComboBox.insertItem(0, t)
  1098.  
  1099.             if s is not None:
  1100.                 StartComboBox.setCurrentIndex(StartComboBox.findText(s))
  1101.  
  1102.             if e is not None:
  1103.                 EndComboBox.setCurrentIndex(EndComboBox.findText(e))
  1104.  
  1105.             if value is not None and \
  1106.                 value[0].lower() == default[0].lower() and \
  1107.                 value[1].lower() == default[1].lower():
  1108.  
  1109.                 DefaultButton.setEnabled(False)
  1110.  
  1111.             self.connect(StartComboBox, SIGNAL("activated(const QString&)"), self.BannerComboBox_activated)
  1112.             self.connect(EndComboBox, SIGNAL("activated(const QString&)"), self.BannerComboBox_activated)
  1113.             self.connect(DefaultButton, SIGNAL("clicked()"), self.DefaultButton_clicked)
  1114.  
  1115.         elif typ == cups.PPD_UI_PICKMANY:
  1116.             log.error("Unrecognized type: pickmany")
  1117.  
  1118.         elif typ == cups.UI_UNITS_SPINNER:
  1119.             log.error("Unrecognized type: units spinner")
  1120.  
  1121.         elif typ == cups.UI_PAGE_RANGE:
  1122.             HBoxLayout = QHBoxLayout()
  1123.             HBoxLayout.setObjectName("HBoxLayout")
  1124.  
  1125.             OptionLabel = QLabel(self.widget)
  1126.             OptionLabel.setObjectName("OptionLabel")
  1127.             HBoxLayout.addWidget(OptionLabel)
  1128.  
  1129.             SpacerItem = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
  1130.             HBoxLayout.addItem(SpacerItem)
  1131.  
  1132.             GroupBox = QFrame(self.widget)
  1133.  
  1134.             gridlayout1 = QGridLayout(GroupBox)
  1135.  
  1136.             AllRadioButton = PageRangeRadioButton(GroupBox, "AllRadioButton",
  1137.                                                self.group, option, default)
  1138.  
  1139.             gridlayout1.addWidget(AllRadioButton,0,0,1,1)
  1140.             RangeRadioButton = PageRangeRadioButton(GroupBox, "RangeRadioButton",
  1141.                                                  self.group, option, default)
  1142.  
  1143.             gridlayout1.addWidget(RangeRadioButton,0,1,1,1)
  1144.             HBoxLayout.addWidget(GroupBox)
  1145.  
  1146.             PageRangeEdit = QLineEdit(self.widget)
  1147.             HBoxLayout.addWidget(PageRangeEdit)
  1148.             PageRangeEdit.setValidator(RangeValidator(PageRangeEdit))
  1149.  
  1150.             AllRadioButton.setRangeEdit(PageRangeEdit)
  1151.             RangeRadioButton.setRangeEdit(PageRangeEdit)
  1152.  
  1153.             DefaultButton = DefaultPushButton(self.widget, "defaultPushButton", self.group, option,
  1154.                 choices, default, (AllRadioButton, RangeRadioButton, PageRangeEdit), typ, job_option)
  1155.  
  1156.             AllRadioButton.setDefaultPushbutton(DefaultButton)
  1157.             RangeRadioButton.setDefaultPushbutton(DefaultButton)
  1158.  
  1159.             HBoxLayout.addWidget(DefaultButton)
  1160.             self.gridlayout.addLayout(HBoxLayout, self.row, 0, 1, 1)
  1161.  
  1162.             OptionLabel.setText(text)
  1163.             AllRadioButton.setText(self.__tr("All pages"))
  1164.             RangeRadioButton.setText(self.__tr("Page Range:"))
  1165.  
  1166.             DefaultButton.setText("Default")
  1167.             DefaultButton.setEnabled(False)
  1168.  
  1169.             AllRadioButton.setChecked(True)
  1170.             PageRangeEdit.setEnabled(False)
  1171.  
  1172.             # TODO: Set current
  1173.  
  1174.             self.connect(AllRadioButton, SIGNAL("toggled(bool)"), self.PageRangeAllRadio_toggled)
  1175.             self.connect(RangeRadioButton, SIGNAL("toggled(bool)"), self.PageRangeRangeRadio_toggled)
  1176.             self.connect(DefaultButton, SIGNAL("clicked()"), self.DefaultButton_clicked)
  1177.             self.connect(PageRangeEdit, SIGNAL("textChanged(const QString &)"), self.PageRangeEdit_textChanged)
  1178.             self.connect(PageRangeEdit, SIGNAL("editingFinished()"), self.PageRangeEdit_editingFinished)
  1179.  
  1180.         elif typ == cups.UI_JOB_STORAGE_MODE:
  1181.             HBoxLayout = QHBoxLayout()
  1182.             HBoxLayout.setObjectName("HBoxLayout")
  1183.  
  1184.             OptionLabel = QLabel(self.widget)
  1185.             OptionLabel.setObjectName("OptionLabel")
  1186.             HBoxLayout.addWidget(OptionLabel)
  1187.  
  1188.             SpacerItem = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
  1189.             HBoxLayout.addItem(SpacerItem)
  1190.  
  1191.             self.JobStorageModeComboBox = QComboBox(self.widget)
  1192.             HBoxLayout.addWidget(self.JobStorageModeComboBox)
  1193.  
  1194.             self.JobStorageModeDefaultButton = QPushButton(self.widget)
  1195.             HBoxLayout.addWidget(self.JobStorageModeDefaultButton)
  1196.  
  1197.             self.gridlayout.addLayout(HBoxLayout, self.row, 0, 1, 1)
  1198.  
  1199.             OptionLabel.setText(text)
  1200.             self.JobStorageModeDefaultButton.setText(self.__tr("Default"))
  1201.  
  1202.             self.JobStorageModeComboBox.addItem(self.__tr("Off/Disabled"), QVariant(JOB_STORAGE_TYPE_OFF))
  1203.             self.JobStorageModeComboBox.addItem(self.__tr("Proof and Hold"), QVariant(JOB_STORAGE_TYPE_PROOF_AND_HOLD))
  1204.             self.JobStorageModeComboBox.addItem(self.__tr("Personal/Private Job"), QVariant(JOB_STORAGE_TYPE_PERSONAL))
  1205.             self.JobStorageModeComboBox.addItem(self.__tr("Quick Copy"), QVariant(JOB_STORAGE_TYPE_QUICK_COPY))
  1206.             self.JobStorageModeComboBox.addItem(self.__tr("Stored Job"), QVariant(JOB_STORAGE_TYPE_STORE))
  1207.  
  1208.             self.connect(self.JobStorageModeComboBox, SIGNAL("activated(int)"),
  1209.                         self.JobStorageModeComboBox_activated)
  1210.  
  1211.             self.connect(self.JobStorageModeDefaultButton, SIGNAL("clicked()"),
  1212.                         self.JobStorageModeDefaultButton_clicked)
  1213.  
  1214.  
  1215.         elif typ == cups.UI_JOB_STORAGE_PIN:
  1216.             HBoxLayout = QHBoxLayout()
  1217.             HBoxLayout.setObjectName("HBoxLayout")
  1218.  
  1219.             OptionLabel = QLabel(self.widget)
  1220.             OptionLabel.setObjectName("OptionLabel")
  1221.             HBoxLayout.addWidget(OptionLabel)
  1222.  
  1223.             SpacerItem = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
  1224.             HBoxLayout.addItem(SpacerItem)
  1225.  
  1226.             self.JobStoragePinGroupBox = QFrame(self.widget)
  1227.  
  1228.             gridlayout1 = QGridLayout(self.JobStoragePinGroupBox)
  1229.             self.JobStoragePinOffRadioButton = QRadioButton(self.JobStoragePinGroupBox)
  1230.             gridlayout1.addWidget(self.JobStoragePinOffRadioButton, 0, 0, 1, 1)
  1231.  
  1232.             self.JobStoragePinPrivateRadioButton = QRadioButton(self.JobStoragePinGroupBox)
  1233.             gridlayout1.addWidget(self.JobStoragePinPrivateRadioButton, 0, 1, 1, 1)
  1234.  
  1235.             self.JobStoragePinEdit = QLineEdit(self.JobStoragePinGroupBox)
  1236.             self.JobStoragePinEdit.setMaxLength(4)
  1237.             self.JobStoragePinEdit.setValidator(PinValidator(self.JobStoragePinEdit))
  1238.             gridlayout1.addWidget(self.JobStoragePinEdit, 0, 2, 1, 1)
  1239.  
  1240.             HBoxLayout.addWidget(self.JobStoragePinGroupBox)
  1241.  
  1242.             self.JobStoragePinDefaultButton = QPushButton(self.widget)
  1243.             HBoxLayout.addWidget(self.JobStoragePinDefaultButton)
  1244.  
  1245.             self.JobStoragePinOffRadioButton.setText(self.__tr("Public/Off"))
  1246.             self.JobStoragePinPrivateRadioButton.setText(self.__tr("Private/Use PIN:"))
  1247.  
  1248.             self.gridlayout.addLayout(HBoxLayout, self.row, 0, 1, 1)
  1249.  
  1250.             OptionLabel.setText(text)
  1251.             self.JobStoragePinDefaultButton.setText(self.__tr("Default"))
  1252.  
  1253.             self.connect(self.JobStoragePinOffRadioButton, SIGNAL("toggled(bool)"),
  1254.                             self.JobStoragePinOffRadioButton_toggled)
  1255.  
  1256.             self.connect(self.JobStoragePinPrivateRadioButton, SIGNAL("toggled(bool)"),
  1257.                             self.JobStoragePinPrivateRadioButton_toggled)
  1258.  
  1259.             self.connect(self.JobStoragePinDefaultButton, SIGNAL("clicked()"),
  1260.                             self.JobStoragePinDefaultButton_clicked)
  1261.  
  1262.             self.connect(self.JobStoragePinEdit, SIGNAL("textEdited(const QString &)"),
  1263.                         self.JobStoragePinEdit_textEdited)
  1264.  
  1265.  
  1266.         elif typ == cups.UI_JOB_STORAGE_USERNAME:
  1267.             HBoxLayout = QHBoxLayout()
  1268.             HBoxLayout.setObjectName("HBoxLayout")
  1269.  
  1270.             OptionLabel = QLabel(self.widget)
  1271.             OptionLabel.setObjectName("OptionLabel")
  1272.             HBoxLayout.addWidget(OptionLabel)
  1273.             OptionLabel.setText(text)
  1274.  
  1275.             SpacerItem = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
  1276.             HBoxLayout.addItem(SpacerItem)
  1277.  
  1278.             self.JobStorageUsernameGroupBox = QFrame(self.widget)
  1279.  
  1280.             gridlayout1 = QGridLayout(self.JobStorageUsernameGroupBox)
  1281.             self.JobStorageUsernameAutoRadioButton = QRadioButton(self.JobStorageUsernameGroupBox)
  1282.             gridlayout1.addWidget(self.JobStorageUsernameAutoRadioButton, 0, 0, 1, 1)
  1283.  
  1284.             self.JobStorageUsernameCustomRadioButton = QRadioButton(self.JobStorageUsernameGroupBox)
  1285.             gridlayout1.addWidget(self.JobStorageUsernameCustomRadioButton, 0, 1, 1, 1)
  1286.  
  1287.             self.JobStorageUsernameEdit = QLineEdit(self.JobStorageUsernameGroupBox)
  1288.             self.JobStorageUsernameEdit.setValidator(UsernameAndJobnameValidator(self.JobStorageUsernameEdit))
  1289.             self.JobStorageUsernameEdit.setMaxLength(16)
  1290.             gridlayout1.addWidget(self.JobStorageUsernameEdit, 0, 2, 1, 1)
  1291.  
  1292.             HBoxLayout.addWidget(self.JobStorageUsernameGroupBox)
  1293.  
  1294.             self.JobStorageUsernameDefaultButton = QPushButton(self.widget)
  1295.             HBoxLayout.addWidget(self.JobStorageUsernameDefaultButton)
  1296.  
  1297.             self.JobStorageUsernameAutoRadioButton.setText(self.__tr("Automatic"))
  1298.             self.JobStorageUsernameCustomRadioButton.setText(self.__tr("Custom:"))
  1299.             self.JobStorageUsernameDefaultButton.setText(self.__tr("Default"))
  1300.  
  1301.             self.connect(self.JobStorageUsernameAutoRadioButton, SIGNAL("toggled(bool)"),
  1302.                             self.JobStorageUsernameAutoRadioButton_toggled)
  1303.  
  1304.             self.connect(self.JobStorageUsernameCustomRadioButton, SIGNAL("toggled(bool)"),
  1305.                             self.JobStorageUsernameCustomRadioButton_toggled)
  1306.  
  1307.             self.connect(self.JobStorageUsernameDefaultButton, SIGNAL("clicked()"),
  1308.                         self.JobStorageUsernameDefaultButton_clicked)
  1309.  
  1310.             self.connect(self.JobStorageUsernameEdit, SIGNAL("textEdited(const QString &)"),
  1311.                         self.JobStorageUsernameEdit_textEdited)
  1312.  
  1313.             self.gridlayout.addLayout(HBoxLayout, self.row, 0, 1, 1)
  1314.  
  1315.         elif typ == cups.UI_JOB_STORAGE_ID:
  1316.             HBoxLayout = QHBoxLayout()
  1317.             HBoxLayout.setObjectName("HBoxLayout")
  1318.  
  1319.             OptionLabel = QLabel(self.widget)
  1320.             OptionLabel.setObjectName("OptionLabel")
  1321.             HBoxLayout.addWidget(OptionLabel)
  1322.             OptionLabel.setText(text)
  1323.  
  1324.             SpacerItem = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
  1325.             HBoxLayout.addItem(SpacerItem)
  1326.  
  1327.             self.JobStorageIDGroupBox = QFrame(self.widget)
  1328.  
  1329.             gridlayout1 = QGridLayout(self.JobStorageIDGroupBox)
  1330.             self.JobStorageIDAutoRadioButton = QRadioButton(self.JobStorageIDGroupBox)
  1331.             gridlayout1.addWidget(self.JobStorageIDAutoRadioButton, 0, 0, 1, 1)
  1332.  
  1333.             self.JobStorageIDCustomRadioButton = QRadioButton(self.JobStorageIDGroupBox)
  1334.             gridlayout1.addWidget(self.JobStorageIDCustomRadioButton, 0, 1, 1, 1)
  1335.  
  1336.             self.JobStorageIDEdit = QLineEdit(self.JobStorageIDGroupBox)
  1337.             self.JobStorageIDEdit.setValidator(UsernameAndJobnameValidator(self.JobStorageIDEdit))
  1338.             self.JobStorageIDEdit.setMaxLength(16)
  1339.             gridlayout1.addWidget(self.JobStorageIDEdit, 0, 2, 1, 1)
  1340.  
  1341.             HBoxLayout.addWidget(self.JobStorageIDGroupBox)
  1342.  
  1343.             self.JobStorageIDDefaultButton = QPushButton(self.widget)
  1344.             HBoxLayout.addWidget(self.JobStorageIDDefaultButton)
  1345.  
  1346.             self.JobStorageIDAutoRadioButton.setText(self.__tr("Automatic"))
  1347.             self.JobStorageIDCustomRadioButton.setText(self.__tr("Custom:"))
  1348.             self.JobStorageIDDefaultButton.setText(self.__tr("Default"))
  1349.  
  1350.             self.connect(self.JobStorageIDAutoRadioButton, SIGNAL("toggled(bool)"),
  1351.                             self.JobStorageIDAutoRadioButton_toggled)
  1352.  
  1353.             self.connect(self.JobStorageIDCustomRadioButton, SIGNAL("toggled(bool)"),
  1354.                             self.JobStorageIDCustomRadioButton_toggled)
  1355.  
  1356.             self.connect(self.JobStorageIDDefaultButton, SIGNAL("clicked()"),
  1357.                         self.JobStorageIDDefaultButton_clicked)
  1358.  
  1359.             self.connect(self.JobStorageIDEdit, SIGNAL("textEdited(const QString &)"),
  1360.                         self.JobStorageIDEdit_textEdited)
  1361.  
  1362.             self.gridlayout.addLayout(HBoxLayout, self.row, 0, 1, 1)
  1363.  
  1364.         elif typ == cups.UI_JOB_STORAGE_ID_EXISTS:
  1365.             HBoxLayout = QHBoxLayout()
  1366.             HBoxLayout.setObjectName("HBoxLayout")
  1367.  
  1368.             OptionLabel = QLabel(self.widget)
  1369.             OptionLabel.setObjectName("OptionLabel")
  1370.             HBoxLayout.addWidget(OptionLabel)
  1371.             OptionLabel.setText(text)
  1372.  
  1373.             SpacerItem = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
  1374.             HBoxLayout.addItem(SpacerItem)
  1375.  
  1376.             self.JobStorageExistingComboBox = QComboBox(self.widget)
  1377.             HBoxLayout.addWidget(self.JobStorageExistingComboBox)
  1378.  
  1379.             self.JobStorageExistingDefaultButton = QPushButton(self.widget)
  1380.             HBoxLayout.addWidget(self.JobStorageExistingDefaultButton)
  1381.  
  1382.             self.JobStorageExistingComboBox.addItem(self.__tr("Replace existing job"),
  1383.                              QVariant(JOB_STORAGE_EXISTING_JOB_REPLACE))
  1384.  
  1385.             self.JobStorageExistingComboBox.addItem(self.__tr("Use job name appended with 1-99"),
  1386.                              QVariant(JOB_STORAGE_EXISTING_JOB_APPEND_1_99))
  1387.  
  1388.             self.JobStorageExistingDefaultButton.setText(self.__tr("Default"))
  1389.  
  1390.             self.gridlayout.addLayout(HBoxLayout, self.row, 0, 1, 1)
  1391.  
  1392.             self.connect(self.JobStorageExistingComboBox, SIGNAL("activated(int)"),
  1393.                         self.JobStorageExistingComboBox_activated)
  1394.  
  1395.             self.connect(self.JobStorageExistingDefaultButton, SIGNAL("clicked()"),
  1396.                         self.JobStorageExistingDefaultButton_clicked)
  1397.  
  1398.         else:
  1399.             log.error("Invalid UI value: %s/%s" % (self.group, option))
  1400.  
  1401.         self.row += 1
  1402.  
  1403.  
  1404.  
  1405.     def BannerComboBox_activated(self, a): # cups.UI_BANNER_JOB_SHEETS
  1406.         a = unicode(a)
  1407.         sender = self.sender()
  1408.         choice = None
  1409.  
  1410.         start, end = None, None
  1411.         for c, t in sender.choices:
  1412.             if t == a:
  1413.                 start = c
  1414.                 break
  1415.  
  1416.         for c, t in sender.other.choices:
  1417.             if t == sender.other.currentText():
  1418.                 end = c
  1419.                 break
  1420.  
  1421.         if sender.option == 'end':
  1422.             start, end = end, start
  1423.  
  1424.         if start is not None and \
  1425.             end is not None and \
  1426.             start.lower() == sender.default[0].lower() and \
  1427.             end.lower() == sender.default[1].lower():
  1428.                 self.removePrinterOption('job-sheets')
  1429.                 sender.pushbutton.setEnabled(False)
  1430.         else:
  1431.             sender.pushbutton.setEnabled(True)
  1432.  
  1433.             if start is not None and \
  1434.                 end is not None:
  1435.  
  1436.                 self.setPrinterOption('job-sheets', ','.join([start, end]))
  1437.  
  1438.  
  1439.     def ComboBox_highlighted(self, t):
  1440.         t = unicode(t)
  1441.         sender = self.sender()
  1442.         choice = None
  1443.  
  1444.         #print sender, sender.option, sender.job_option
  1445.  
  1446.         choice = None
  1447.         for c, a in sender.choices:
  1448.             if a == t:
  1449.                 choice = c
  1450.                 break
  1451.  
  1452.         if choice is not None and choice == sender.default:
  1453.             if sender.job_option:
  1454.                 self.job_options[sender.option] = sender.default
  1455.             else:
  1456.                 self.removePrinterOption(sender.option)
  1457.             sender.pushbutton.setEnabled(False)
  1458.  
  1459.         else:
  1460.             sender.pushbutton.setEnabled(True)
  1461.  
  1462.             if choice is not None:
  1463.                 if sender.job_option:
  1464.                     self.job_options[sender.option] = choice
  1465.                 else:
  1466.                     self.setPrinterOption(sender.option, choice)
  1467.  
  1468.             #self.linkPrintoutModeAndQuality(sender.option, choice)
  1469.  
  1470.     if 0:
  1471.         pass
  1472.         #    def linkPrintoutModeAndQuality(self, option, choice):
  1473.         #        if option.lower() == 'quality' and \
  1474.         #            choice is not None:
  1475.         #
  1476.         #            try:
  1477.         #                c = self.items['o:PrintoutMode'].control
  1478.         #            except KeyError:
  1479.         #                return
  1480.         #            else:
  1481.         #                if c is not None:
  1482.         #                    if choice.lower() == 'fromprintoutmode':
  1483.         #                        # from printoutmode selected
  1484.         #                        # determine printoutmode option combo enable state
  1485.         #                        c.setEnabled(True)
  1486.         #                        QToolTip.remove(c)
  1487.         #                        a = unicode(c.currentText())
  1488.         #
  1489.         #                        # determine printoutmode default button state
  1490.         #                        link_choice = None
  1491.         #                        for x, t in c.choices:
  1492.         #                            if t == a:
  1493.         #                                link_choice = x
  1494.         #                                break
  1495.         #
  1496.         #                        if link_choice is not None and \
  1497.         #                            link_choice.lower() == c.default.lower():
  1498.         #
  1499.         #                            c.pushbutton.setEnabled(False)
  1500.         #                        else:
  1501.         #                            c.pushbutton.setEnabled(True)
  1502.         #
  1503.         #                    else: # fromprintoutmode not selected, disable printoutmode
  1504.         #                        c.setEnabled(False)
  1505.         #                        QToolTip.add(c, self.__tr("""Set Quality to "Controlled by 'Printout Mode'" to enable."""))
  1506.         #                        c.pushbutton.setEnabled(False)
  1507.         #
  1508.  
  1509.     def SpinBox_valueChanged(self, i): # cups.UI_SPINNER
  1510.         sender = self.sender()
  1511.  
  1512.         if not sender.job_option:
  1513.             if i == sender.default:
  1514.                 self.removePrinterOption(sender.option)
  1515.                 sender.pushbutton.setEnabled(False)
  1516.             else:
  1517.                 sender.pushbutton.setEnabled(True)
  1518.                 self.setPrinterOption(sender.option, str(i))
  1519.  
  1520.         else:
  1521.             try:
  1522.                 self.job_options[sender.option] = int(i)
  1523.             except ValueError:
  1524.                 self.job_options[sender.option] = sender.default
  1525.  
  1526.  
  1527.     def BoolRadioButtons_clicked(self, b): # cups.PPD_UI_BOOLEAN
  1528.         sender = self.sender()
  1529.         b = int(b)
  1530.  
  1531.         if b == sender.default:
  1532.             self.removePrinterOption(sender.option)
  1533.             sender.pushbutton.setEnabled(False)
  1534.         else:
  1535.             sender.pushbutton.setEnabled(True)
  1536.  
  1537.             if b:
  1538.                 self.setPrinterOption(sender.option, "true")
  1539.             else:
  1540.                 self.setPrinterOption(sender.option, "false")
  1541.  
  1542.  
  1543.     def DefaultButton_clicked(self):
  1544.         sender = self.sender()
  1545.         sender.setEnabled(False)
  1546.  
  1547.         if sender.typ == cups.PPD_UI_BOOLEAN: # () On  (*) Off
  1548.             if sender.default:
  1549.                 sender.control[0].setChecked(True)
  1550.                 sender.control[0].setFocus(Qt.OtherFocusReason)
  1551.             else:
  1552.                 sender.control[1].setChecked(True)
  1553.                 sender.control[1].setFocus(Qt.OtherFocusReason)
  1554.  
  1555.             if not sender.job_option:
  1556.                 self.removePrinterOption(sender.option)
  1557.  
  1558.         elif sender.typ == cups.PPD_UI_PICKONE: # [     \/]
  1559.             choice, text = None, None
  1560.  
  1561.             for c, t in sender.choices:
  1562.                 if c == sender.default:
  1563.                     choice = c
  1564.                     text = t
  1565.                     self.job_options[sender.option] = t
  1566.                     break
  1567.  
  1568.             if choice is not None:
  1569.                 if not sender.job_option:
  1570.                     self.removePrinterOption(sender.option)
  1571.                 index = sender.control.findText(text)
  1572.                 sender.control.setCurrentIndex(index)
  1573.  
  1574.                 #self.linkPrintoutModeAndQuality(sender.option, choice) # TODO:
  1575.                 sender.control.setFocus(Qt.OtherFocusReason)
  1576.  
  1577.         elif sender.typ == cups.UI_SPINNER: # [ x /\|\/]
  1578.             sender.control.setValue(sender.default)
  1579.             if not sender.job_option:
  1580.                 self.removePrinterOption(sender.option)
  1581.  
  1582.             sender.control.setFocus(Qt.OtherFocusReason)
  1583.  
  1584.         elif sender.typ == cups.UI_BANNER_JOB_SHEETS: # start: [     \/]  end: [     \/]
  1585.             start, end, start_text, end_text = None, None, None, None
  1586.             for c, t in sender.choices:
  1587.                 if c == sender.default[0]:
  1588.                     start = c
  1589.                     start_text = t
  1590.  
  1591.                 if c == sender.default[1]:
  1592.                     end = c
  1593.                     end_text = t
  1594.  
  1595.             if start is not None:
  1596.                 index = sender.control[0].findText(start_text)
  1597.                 sender.control[0].setCurrentIndex(index)
  1598.  
  1599.             if end is not None:
  1600.                 index = sender.control[1].findText(end_text)
  1601.                 sender.control[1].setCurrentIndex(index)
  1602.  
  1603.             if not sender.job_option:
  1604.                 self.removePrinterOption('job-sheets')
  1605.  
  1606.             sender.control[0].setFocus(Qt.OtherFocusReason)
  1607.  
  1608.         elif sender.typ == cups.UI_PAGE_RANGE: # (*) All () Pages: [    ]
  1609.             sender.control[0].setChecked(True) # all radio button
  1610.             sender.control[0].setFocus(Qt.OtherFocusReason)
  1611.             sender.control[2].setEnabled(False) # range edit box
  1612.  
  1613.  
  1614.     def PageRangeAllRadio_toggled(self, b):
  1615.         if b:
  1616.             sender = self.sender()
  1617.             sender.edit_control.setEnabled(False)
  1618.             sender.pushbutton.setEnabled(False)
  1619.             self.job_options['pagerange'] = ''
  1620.  
  1621.  
  1622.     def PageRangeRangeRadio_toggled(self, b):
  1623.         if b:
  1624.             sender = self.sender()
  1625.             sender.pushbutton.setEnabled(True)
  1626.             sender.edit_control.setEnabled(True)
  1627.             self.job_options['pagerange'] = unicode(sender.edit_control.text())
  1628.  
  1629.  
  1630.     def PageRangeEdit_editingFinished(self):
  1631.         sender, x = self.sender(), []
  1632.         t, ok = unicode(sender.text()), True
  1633.         try:
  1634.             x = utils.expand_range(t)
  1635.         except ValueError:
  1636.             ok = False
  1637.  
  1638.         if ok:
  1639.             if 0 in x:
  1640.                 ok = False
  1641.  
  1642.             if ok:
  1643.                 for y in x:
  1644.                     if y > 999:
  1645.                         ok = False
  1646.                         break
  1647.  
  1648.         if ok:
  1649.             t = utils.collapse_range(x)
  1650.             sender.setText(QString(t))
  1651.             self.job_options['pagerange'] = t
  1652.  
  1653.         else:
  1654.             self.job_options['pagerange'] = ''
  1655.             log.error("Invalid page range: %s" % t)
  1656.             FailureUI(self, self.__tr("<b>Invalid page range.</b><p>Please enter a range using page numbers (1-999), dashes, and commas. For example: 1-2,3,5-7</p>"))
  1657.             sender.setFocus(Qt.OtherFocusReason)
  1658.  
  1659.  
  1660.     def PageRangeEdit_textChanged(self, t):
  1661.         sender, x, t = self.sender(), [], unicode(t)
  1662.         try:
  1663.             x = utils.expand_range(t)
  1664.         except ValueError:
  1665.             self.job_options['pagerange'] = ''
  1666.             log.error("Invalid page range: %s" % t)
  1667.         else:
  1668.             self.job_options['pagerange'] = t
  1669.  
  1670.  
  1671.     #
  1672.     # Job Storage
  1673.     #
  1674.  
  1675.     def updateJobStorageControls(self):
  1676.         beginWaitCursor()
  1677.         try:
  1678.             # Mode
  1679.             self.JobStorageModeComboBox.setCurrentIndex(self.JobStorageModeComboBox.findData(QVariant(self.job_storage_mode)))
  1680.             self.JobStorageModeDefaultButton.setEnabled(self.job_storage_mode != JOB_STORAGE_TYPE_OFF)
  1681.  
  1682.             # PIN
  1683.             self.JobStoragePinPrivateRadioButton.setChecked(self.job_storage_use_pin)
  1684.  
  1685.             # Username
  1686.             self.JobStorageUsernameAutoRadioButton.setChecked(self.job_storage_auto_username)
  1687.  
  1688.             # Jobname/ID
  1689.             self.JobStorageIDAutoRadioButton.setChecked(self.job_storage_auto_jobname)
  1690.  
  1691.             # Dup/existing ID
  1692.             self.JobStorageExistingComboBox.setCurrentIndex(self.JobStorageExistingComboBox.findData(QVariant(self.job_storage_job_exist)))
  1693.  
  1694.             if self.job_storage_mode == JOB_STORAGE_TYPE_OFF:
  1695.                 # PIN
  1696.                 self.JobStoragePinGroupBox.setEnabled(False)
  1697.                 self.JobStoragePinEdit.setEnabled(False)
  1698.                 self.JobStoragePinDefaultButton.setEnabled(False)
  1699.                 self.JobStoragePinEdit.setText(QString())
  1700.  
  1701.                 # Username
  1702.                 self.JobStorageUsernameGroupBox.setEnabled(False)
  1703.                 self.JobStorageUsernameEdit.setEnabled(False)
  1704.                 self.JobStorageUsernameDefaultButton.setEnabled(False)
  1705.  
  1706.                 # Jobname/ID
  1707.                 self.JobStorageIDGroupBox.setEnabled(False)
  1708.                 self.JobStorageIDEdit.setEnabled(False)
  1709.                 self.JobStorageIDDefaultButton.setEnabled(False)
  1710.  
  1711.                 # Duplicate/existing Jobname/ID
  1712.                 self.JobStorageExistingComboBox.setEnabled(False)
  1713.  
  1714.             else:
  1715.                 # PIN
  1716.                 if self.job_storage_mode in (JOB_STORAGE_TYPE_PERSONAL, JOB_STORAGE_TYPE_STORE):
  1717.                     self.JobStoragePinGroupBox.setEnabled(True)
  1718.                     self.JobStoragePinDefaultButton.setEnabled(self.job_storage_use_pin)
  1719.                     self.JobStoragePinEdit.setEnabled(self.job_storage_use_pin)
  1720.                     self.JobStoragePinEdit.setText(QString(self.job_storage_pin))
  1721.                 else:
  1722.                     self.JobStoragePinGroupBox.setEnabled(False)
  1723.                     self.JobStoragePinEdit.setEnabled(False)
  1724.                     self.JobStoragePinDefaultButton.setEnabled(False)
  1725.                     self.JobStoragePinEdit.setText(QString())
  1726.  
  1727.                 # Username
  1728.                 self.JobStorageUsernameGroupBox.setEnabled(True)
  1729.                 self.JobStorageUsernameEdit.setEnabled(not self.job_storage_auto_username)
  1730.                 self.JobStorageUsernameDefaultButton.setEnabled(not self.job_storage_auto_username)
  1731.                 self.JobStorageUsernameEdit.setText(QString(self.job_storage_username))
  1732.  
  1733.                 # Jobname/ID
  1734.                 self.JobStorageIDGroupBox.setEnabled(True)
  1735.                 self.JobStorageIDEdit.setEnabled(not self.job_storage_auto_jobname)
  1736.                 self.JobStorageIDDefaultButton.setEnabled(not self.job_storage_auto_jobname)
  1737.                 self.JobStorageIDEdit.setText(QString(self.job_storage_jobname))
  1738.  
  1739.                 # Duplicate/existing JobName/ID
  1740.                 self.JobStorageExistingComboBox.setEnabled(not self.job_storage_auto_jobname)
  1741.                 self.JobStorageExistingDefaultButton.setEnabled(not self.job_storage_auto_jobname and self.job_storage_job_exist != JOB_STORAGE_EXISTING_JOB_REPLACE)
  1742.  
  1743.         finally:
  1744.             endWaitCursor()
  1745.  
  1746.  
  1747.     def saveJobStorageOptions(self):
  1748.         beginWaitCursor()
  1749.         try:
  1750.             log.debug("Saving job storage options...")
  1751.  
  1752.             if self.job_storage_mode == JOB_STORAGE_TYPE_OFF:
  1753.                 log.debug("Job storage mode = JOB_STORAGE_TYPE_OFF")
  1754.                 self.setPrinterOption('HOLD', 'OFF')
  1755.                 self.removePrinterOption('HOLDTYPE')
  1756.                 self.removePrinterOption('USERNAME')
  1757.                 self.removePrinterOption('JOBNAME')
  1758.                 self.removePrinterOption('DUPLICATEJOB')
  1759.  
  1760.             elif self.job_storage_mode == JOB_STORAGE_TYPE_PROOF_AND_HOLD:
  1761.                 log.debug("Job storage mode = JOB_STORAGE_TYPE_PROOF_AND_HOLD")
  1762.                 self.setPrinterOption('HOLD', 'PROOF')
  1763.                 #self.removePrinterOption('HOLDTYPE')
  1764.                 self.setPrinterOption('HOLDTYPE', 'PUBLIC')
  1765.  
  1766.             elif self.job_storage_mode == JOB_STORAGE_TYPE_PERSONAL:
  1767.                 log.debug("Job storage mode = JOB_STORAGE_TYPE_PERSONAL")
  1768.  
  1769.                 if self.job_storage_use_pin:
  1770.                     self.setPrinterOption('HOLD', 'ON')
  1771.                 else:
  1772.                     self.setPrinterOption('HOLD', 'PROOF')
  1773.                     self.setPrinterOption('HOLDTYPE', 'PUBLIC')
  1774.  
  1775.  
  1776.             elif self.job_storage_mode == JOB_STORAGE_TYPE_QUICK_COPY:
  1777.                 log.debug("Job storage mode = JOB_STORAGE_TYPE_QUICK_COPY")
  1778.                 self.setPrinterOption('HOLD', 'ON')
  1779.                 self.setPrinterOption('HOLDTYPE', 'PUBLIC')
  1780.  
  1781.             elif self.job_storage_mode == JOB_STORAGE_TYPE_STORE:
  1782.                 log.debug("Job storage mode = JOB_STORAGE_TYPE_STORE")
  1783.                 self.setPrinterOption('HOLD', 'STORE')
  1784.  
  1785.                 if not self.job_storage_use_pin:
  1786.                     self.removePrinterOption('HOLDTYPE')
  1787.  
  1788.             # PIN
  1789.             log.debug("Job storage use pin = %d" % self.job_storage_use_pin)
  1790.             if self.job_storage_use_pin:
  1791.                 self.setPrinterOption('HOLDTYPE', 'PRIVATE')
  1792.  
  1793.             #else:
  1794.             #    self.removePrinterOption('HOLDKEY')
  1795.  
  1796.             # Dup/exisiting
  1797.             if self.job_storage_job_exist == JOB_STORAGE_EXISTING_JOB_REPLACE:
  1798.                 log.debug("Job storage duplicate = JOB_STORAGE_EXISTING_JOB_REPLACE")
  1799.                 self.setPrinterOption('DUPLICATEJOB', 'REPLACE')
  1800.  
  1801.             else: # JOB_STORAGE_EXISTING_JOB_APPEND_1_99
  1802.                 log.debug("Job storage duplicate = JOB_STORAGE_EXISTING_JOB_APPEND_1_99")
  1803.                 self.setPrinterOption('DUPLICATEJOB', 'APPEND')
  1804.  
  1805.  
  1806.         finally:
  1807.             endWaitCursor()
  1808.  
  1809.  
  1810.     #
  1811.     # Mode
  1812.     #
  1813.  
  1814.     def JobStorageModeComboBox_activated(self, i):
  1815.         sender = self.sender()
  1816.         mode, ok = sender.itemData(i).toInt()
  1817.         if ok:
  1818.             self.job_storage_mode = mode
  1819.             self.saveJobStorageOptions()
  1820.             self.updateJobStorageControls()
  1821.  
  1822.  
  1823.     def JobStorageModeDefaultButton_clicked(self):
  1824.         self.JobStorageModeComboBox.emit(SIGNAL("activated(int)"), JOB_STORAGE_TYPE_OFF)
  1825.  
  1826.  
  1827.     #
  1828.     # PIN
  1829.     #
  1830.  
  1831.     def JobStoragePinOffRadioButton_toggled(self, b):
  1832.         self.job_storage_use_pin = not b
  1833.         self.updateJobStorageControls()
  1834.         self.saveJobStorageOptions()
  1835.  
  1836.  
  1837.     def JobStoragePinPrivateRadioButton_toggled(self, b):
  1838.         self.job_storage_use_pin = b
  1839.         self.updateJobStorageControls()
  1840.         self.saveJobStorageOptions()
  1841.  
  1842.  
  1843.     def JobStoragePinDefaultButton_clicked(self):
  1844.         self.JobStoragePinOffRadioButton.emit(SIGNAL("toggled(bool)"), True)
  1845.  
  1846.  
  1847.     def JobStoragePinEdit_textEdited(self, s):
  1848.         self.job_storage_pin = unicode(s)
  1849.         self.setPrinterOption('HOLDKEY', self.job_storage_pin.encode('ascii'))
  1850.  
  1851.  
  1852.  
  1853.     #
  1854.     # Username
  1855.     #
  1856.  
  1857.     def JobStorageUsernameAutoRadioButton_toggled(self, b):
  1858.         self.job_storage_auto_username = b
  1859.         self.updateJobStorageControls()
  1860.         self.saveJobStorageOptions()
  1861.  
  1862.  
  1863.     def JobStorageUsernameCustomRadioButton_toggled(self, b):
  1864.         self.job_storage_auto_username = not b
  1865.         self.updateJobStorageControls()
  1866.         self.saveJobStorageOptions()
  1867.  
  1868.  
  1869.     def JobStorageUsernameDefaultButton_clicked(self):
  1870.         self.JobStorageUsernameAutoRadioButton.emit(SIGNAL("toggled(bool)"), True)
  1871.  
  1872.  
  1873.     def JobStorageUsernameEdit_textEdited(self, s):
  1874.         self.job_storage_username = unicode(s)
  1875.         self.setPrinterOption('USERNAME', self.job_storage_username.encode('ascii'))
  1876.  
  1877.     #
  1878.     # Jobname/ID
  1879.     #
  1880.  
  1881.     def JobStorageIDAutoRadioButton_toggled(self, b):
  1882.         self.job_storage_auto_jobname = b
  1883.         self.updateJobStorageControls()
  1884.         self.saveJobStorageOptions()
  1885.  
  1886.  
  1887.     def JobStorageIDCustomRadioButton_toggled(self, b):
  1888.         self.job_storage_auto_jobname = not b
  1889.         self.updateJobStorageControls()
  1890.         self.saveJobStorageOptions()
  1891.  
  1892.  
  1893.     def JobStorageIDDefaultButton_clicked(self):
  1894.         self.JobStorageIDAutoRadioButton.emit(SIGNAL("toggled(bool)"), True)
  1895.  
  1896.  
  1897.     def JobStorageIDEdit_textEdited(self, s):
  1898.         self.job_storage_jobname = unicode(s)
  1899.         self.setPrinterOption('JOBNAME', self.job_storage_jobname.encode('ascii'))
  1900.  
  1901.     #
  1902.     # Duplicate/existing Jobname/ID
  1903.     #
  1904.  
  1905.     def JobStorageExistingComboBox_activated(self, i):
  1906.         sender = self.sender()
  1907.         opt, ok = sender.itemData(i).toInt()
  1908.         if ok:
  1909.             self.job_storage_job_exist = opt
  1910.             self.updateJobStorageControls()
  1911.             self.saveJobStorageOptions()
  1912.  
  1913.  
  1914.     def JobStorageExistingDefaultButton_clicked(self):
  1915.         self.JobStorageExistingComboBox.emit(SIGNAL("activated(int)"), JOB_STORAGE_EXISTING_JOB_REPLACE)
  1916.  
  1917.  
  1918.     #
  1919.     # Printer I/O
  1920.     #
  1921.  
  1922.     def setPrinterOption(self, option, value):
  1923.         log.debug("setPrinterOption(%s, %s)" % (option, value))
  1924.         cups.openPPD(self.cur_printer)
  1925.  
  1926.         try:
  1927.             cups.addOption("%s=%s" % (option, value))
  1928.             cups.setOptions()
  1929.         finally:
  1930.             cups.closePPD()
  1931.  
  1932.     def removePrinterOption(self, option):
  1933.         log.debug("removePrinterOption(%s)" % option)
  1934.         cups.openPPD(self.cur_printer)
  1935.  
  1936.         try:
  1937.             cups.removeOption(option)
  1938.             cups.setOptions()
  1939.         finally:
  1940.             cups.closePPD()
  1941.  
  1942.  
  1943.     def __tr(self,s,c = None):
  1944.         return qApp.translate("PrintSettingsToolbox",s,c)
  1945.